using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ScreenTest.Items;
using ScreenTest.Players;
using System.IO;
using ScreenTest.Constants;

namespace ScreenTest.World
{
    /// <summary>
    /// Class holding all the level information and providing some methods
    /// with which to test collisions
    /// </summary>
    class Level
    {
        const int BLOCK_SIZE = 40;
        Texture2D blockTexture;
        List<BaseItem> items;
        List<Vector2> blocks;
        Vector2 player1Spawn;
        Vector2 player2Spawn;

        const int CellsAcross = 20;
        const int CellsDown = 15;
        ContentManager content;

        public Vector2 Player1Spawn
        {
            get { return player1Spawn; }
        }

        public Vector2 Player2Spawn
        {
            get { return player2Spawn; }
        }

        public Level()
        {
            items = new List<BaseItem>();
            blocks = new List<Vector2>();
            player1Spawn = new Vector2(200, 200);
            player2Spawn = new Vector2(400, 200);
        }

        public void Load(ContentManager content, String levelName)
        {
            blockTexture = content.Load<Texture2D>(@"Content\blk");
            this.content = content;
            

            LoadLevelFile(levelName);

            Reset();
        }

        void LoadLevelFile(String name)
        {
            BinaryReader reader = new BinaryReader(new FileStream(name, FileMode.Open, FileAccess.Read));

            for (int y = 0; y < CellsDown; y++)
            {
                for (int x = 0; x < CellsAcross; x++)
                {
                    int val = reader.ReadInt32();

                    switch (val)
                    {
                        case TileTypes.CELL_PLAYER1:
                            AddPlayer1Spawn(x, y);
                            break;

                        case TileTypes.CELL_PLAYER2:
                            AddPlayer2Spawn(x, y);
                            break;


                        case TileTypes.CELL_ROCKET:
                            AddRocket(x, y);
                            break;

                        case TileTypes.CELL_HEALTH:
                            AddHealth(x, y);
                            break;

                        case TileTypes.CELL_WALL:
                            AddBlock(x, y);
                            break;
                    }
                }
            }

            reader.Close();
        }

        void AddBlock(int x, int y)
        {
            Vector2 block = new Vector2();
            block.X = BLOCK_SIZE * x;
            block.Y = BLOCK_SIZE * y;

            blocks.Add(block);
        }

        void AddPlayer1Spawn(int x, int y)
        {
            player1Spawn = new Vector2(x * BLOCK_SIZE, y * BLOCK_SIZE);
            //player1Spawn = new Vector2(3 * BLOCK_SIZE, 3 * BLOCK_SIZE);
        }

        void AddPlayer2Spawn(int x, int y)
        {
            player2Spawn = new Vector2(x * BLOCK_SIZE, y * BLOCK_SIZE);
        }

        void AddHealth(int x, int y)
        {
            Health health = new Health();
            health.Load(content);
            health.Position = new Vector2(x * BLOCK_SIZE, y * BLOCK_SIZE);
            items.Add(health);
        }

        void AddRocket(int x, int y)
        {
            Rocket rocket = new Rocket();
            rocket.Load(content);
            rocket.Position = new Vector2(x * BLOCK_SIZE, y * BLOCK_SIZE);
            items.Add(rocket);
        }

        public void Reset()
        {
            foreach (BaseItem item in items)
            {
                item.Respawn();
            }
        }

        //void LoadLevelData()
        //{
        //    for (int x = 0; x < 22; x++)
        //    {
        //        for (int y = 0; y < 20; y++)
        //        {
        //            Vector2 block = new Vector2();
        //            block.X = BLOCK_SIZE * x;
        //            block.Y = BLOCK_SIZE * y;

        //            blocks.Add(block);
        //        }
        //    }
        //}

        BoundingBox GetBlockBoundingBox(Vector2 position)
        {
            Vector3 min;
            Vector3 max;

            //min = new Vector3(position.X - BLOCK_SIZE / 2, position.Y - BLOCK_SIZE / 2, 0);
            //max = new Vector3(position.X + BLOCK_SIZE / 2, position.Y + BLOCK_SIZE / 2, 0);

            min = new Vector3(position.X, position.Y, 0);
            max = new Vector3(position.X + BLOCK_SIZE, position.Y + BLOCK_SIZE, 0);

            return new BoundingBox(min, max);
        }

        public bool CollideAndBounce(BoundingBox bbox, out Vector2 resultingVector)
        {
            Vector2 result = new Vector2(0, 0);
            resultingVector = result;
            return false;
        }

        public bool Collides(BoundingBox bbox)
        {
            foreach (Vector2 block in blocks)
            {
                //Would make sense to precalculate all of these
                BoundingBox blockBBox = GetBlockBoundingBox(block);

                if (bbox.Intersects(blockBBox))
                {
                    return true;
                }
            }

            return false;

        }

        //public void CheckPlayerAgainstWorld(Player player)
        //{
        //    Vector2 playerPosition = player.Position;
        //    Vector2 playerVelocity = player.Velocity;

        //    foreach (Vector2 block in blocks)
        //    {
        //        BoundingBox blockBBox = GetBlockBoundingBox(block);
        //        BoundingBox playerBox = player.GetBoundingBox();

        //        BoundingBox xBox = playerBox;
        //        xBox.Min.X += player.Velocity.X;
        //        xBox.Max.X += player.Velocity.X;

        //        //Do we have a collision?
        //        if (blockBBox.Intersects(xBox))
        //        {
        //            //Adjust the players position and velocity accordingly
        //            if (player.Velocity.X > 0)
        //            {
        //                playerPosition.X = blockBBox.Min.X - player.Size / 2 - 1;
        //                playerVelocity.X = 0;
        //            }
        //            else if (player.Velocity.X < 0)
        //            {
        //                playerPosition.X = blockBBox.Max.X + player.Size / 2 + 1;
        //                playerVelocity.X = 0;
        //            }
        //        }

        //        BoundingBox yBox = playerBox;
        //        yBox.Min.Y += player.Velocity.Y;
        //        yBox.Max.Y += player.Velocity.Y;

        //        //Do we have a collision?
        //        if (blockBBox.Intersects(yBox))
        //        {
        //            //Adjust the players position and velocity accordingly
        //            if (player.Velocity.Y > 0)
        //            {
        //                playerPosition.Y = blockBBox.Min.Y - player.Size / 2 - 1;
        //                playerVelocity.Y = 0;
        //            }
        //            else if (player.Velocity.Y < 0)
        //            {
        //                playerPosition.Y = blockBBox.Max.Y + player.Size / 2 + 1;
        //                playerVelocity.Y = 0;
        //            }
        //        }
        //    }

        //    player.Velocity = playerVelocity;
        //    player.Position = playerPosition;
        //}

        public void CheckPlayerAgainstWorld(Player player)
        {
            Vector2 playerPosition = player.Position;
            Vector2 playerVelocity = player.Velocity;

            foreach (Vector2 block in blocks)
            {
                BoundingBox blockBBox = GetBlockBoundingBox(block);
                BoundingBox playerBox = player.GetBoundingBox();

                BoundingBox xBox = playerBox;
                xBox.Min.X += player.Velocity.X;
                xBox.Max.X += player.Velocity.X;

                //Do we have a collision?
                if (blockBBox.Intersects(xBox))
                {
                    //Adjust the players position and velocity accordingly
                    if (player.Velocity.X > 0)
                    {
                        playerPosition.X = blockBBox.Min.X - player.Size - 1;
                        playerVelocity.X = 0;
                    }
                    else if (player.Velocity.X < 0)
                    {
                        playerPosition.X = blockBBox.Max.X + 1;
                        playerVelocity.X = 0;
                    }
                }

                BoundingBox yBox = playerBox;
                yBox.Min.Y += player.Velocity.Y;
                yBox.Max.Y += player.Velocity.Y;

                //Do we have a collision?
                if (blockBBox.Intersects(yBox))
                {
                    //Adjust the players position and velocity accordingly
                    if (player.Velocity.Y > 0)
                    {
                        playerPosition.Y = blockBBox.Min.Y - player.Size - 1;
                        playerVelocity.Y = 0;
                    }
                    else if (player.Velocity.Y < 0)
                    {
                        playerPosition.Y = blockBBox.Max.Y + 1;
                        playerVelocity.Y = 0;
                    }
                }
            }

            player.Velocity = playerVelocity;
            player.Position = playerPosition;
        }

        public void PlayerTouchesItems(Player player)
        {
            foreach (BaseItem item in items)
            {
                item.Touches(player);
            }
        }

        public void Draw(GraphicsDevice device, SpriteBatch spriteBatch)
        {
            Viewport viewport = device.Viewport;
            Rectangle fullscreen = new Rectangle(0, 0, viewport.Width, viewport.Height);

            spriteBatch.Begin();
            foreach (Vector2 block in blocks)
            {
                //spriteBatch.Draw(blockTexture, new Rectangle((int)block.X, (int)block.Y, BLOCK_SIZE, BLOCK_SIZE), null, Color.White, 0f, new Vector2(BLOCK_SIZE/2, BLOCK_SIZE/2), SpriteEffects.None, 0f);
                //spriteBatch.Draw(blockTexture, new Rectangle((int)block.X, (int)block.Y, BLOCK_SIZE, BLOCK_SIZE), null, Color.White, 0f, new Vector2(BLOCK_SIZE / 2, BLOCK_SIZE / 2), SpriteEffects.None, 0f);
                spriteBatch.Draw(blockTexture, new Rectangle((int)block.X, (int)block.Y, BLOCK_SIZE, BLOCK_SIZE), null, Color.White);
            }

            foreach (BaseItem item in items)
            {
                item.Draw(device, spriteBatch);
            }

            spriteBatch.End();
        }

        public void Update(GameTime gameTime)
        {
            foreach (BaseItem item in items)
            {
                item.Update(gameTime);
            }
        }
    }
}
